package com.smartrodin.springbootrabbitmq.config.mybatisplus;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;

import java.util.List;
import java.util.function.Predicate;

/**
 * @author arnold_nie
 * @Date: Created in 2019-08-09 02:08 PM
 * @description: 批量新增数据, 自选字段 insert
 * 来自官网说明：
 * 注意: 这是自选字段 insert !!,如果个别字段在 entity 里为 null 但是数据库中有配置默认值, insert 后数据库字段是为 null 而不是默认值
 * <li> 例1: t -> !t.isLogicDelete() , 表示不要逻辑删除字段 </li>
 * <li> 例2: t -> !t.getProperty().equals("version") , 表示不要字段名为 version 的字段 </li>
 * <li> 例3: t -> t.getFieldFill() != FieldFill.UPDATE) , 表示不要填充策略为 UPDATE 的字段 </li>
 */
public class InsertBatchSomeColumn extends AbstractMethod {

    /**
     * mapper 对应的方法名
     */
    private static final String MAPPER_METHOD = "insertBatchSomeColumn";

    /**
     * 字段筛选条件
     */
    private Predicate<TableFieldInfo> predicate;

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        KeyGenerator keyGenerator = new NoKeyGenerator();
        SqlMethod sqlMethod = SqlMethod.INSERT_ONE;
        List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        String insertSqlColumn = tableInfo.getKeyInsertSqlColumn( false ) +
                this.filterTableFieldInfo( fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY );
        String columnScript = LEFT_BRACKET + insertSqlColumn.substring( 0, insertSqlColumn.length() - 1 ) + RIGHT_BRACKET;
        String insertSqlProperty = tableInfo.getKeyInsertSqlProperty( ENTITY_DOT, false ) +
                this.filterTableFieldInfo( fieldList, predicate, i -> i.getInsertSqlProperty( ENTITY_DOT ), EMPTY );
        insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring( 0, insertSqlProperty.length() - 1 ) + RIGHT_BRACKET;
        String valuesScript = SqlScriptUtils.convertForeach( insertSqlProperty, "list", null, ENTITY, COMMA );
        String keyProperty = null;
        String keyColumn = null;
        // 表包含主键处理逻辑,如果不包含主键当普通字段处理
        if (StringUtils.isNotBlank( tableInfo.getKeyProperty() )) {
            if (tableInfo.getIdType() == IdType.AUTO) {
                /* 自增主键 */
                keyGenerator = new Jdbc3KeyGenerator();
                keyProperty = tableInfo.getKeyProperty();
                keyColumn = tableInfo.getKeyColumn();
            } else {
                if (null != tableInfo.getKeySequence()) {
//                    keyGenerator = TableInfoHelper.genKeyGenerator(tableInfo, builderAssistant, sqlMethod.getMethod(), languageDriver);
                    keyGenerator = TableInfoHelper.genKeyGenerator( sqlMethod.getMethod(), tableInfo, builderAssistant );
                    keyProperty = tableInfo.getKeyProperty();
                    keyColumn = tableInfo.getKeyColumn();
                }
            }
        }
        String sql = String.format( sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript );
        SqlSource sqlSource = languageDriver.createSqlSource( configuration, sql, modelClass );
        return this.addInsertMappedStatement( mapperClass, modelClass, MAPPER_METHOD, sqlSource, keyGenerator, keyProperty, keyColumn );
    }

    public Predicate<TableFieldInfo> getPredicate() {
        return predicate;
    }

    public void setPredicate(Predicate<TableFieldInfo> predicate) {
        this.predicate = predicate;
    }
}